package com.hzit.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.hzit.dao.StudentDao;
import com.hzit.entity.Student;
import com.hzit.service.StudentService;
import com.hzit.util.PageResult;
import com.hzit.vo.StudentVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 类名：
 * 作者：WF
 * 功能：
 */
@Service
@Slf4j
public class StudentServiceImpl implements StudentService {
	@Autowired
	private StudentDao dao;
	// @Autowired
	// private RedisTemplate redisTemplate;
	@Autowired
	private StringRedisTemplate redisTemplate;    // 经常使用
	//1.  查询所有学生
	@Override
	public List<Student> findAll() {
		return dao.findAll();
	}

	//2. 分页查询
	@Override
	public PageResult<Student> findAll(int page, int pageSize) {
		//2.1 开始分页
		Page<Student> studentPage = dao.findAll(PageRequest.of(page-1, pageSize));
		//2.2 返回分页结果
		return new PageResult<>(studentPage.getContent(),new Long(studentPage.getTotalPages()+""));
	}

	//3.  条件查询带分页
	@Override
	public PageResult<Student> findAll(int page, int pageSize, StudentVo vo) {

		Specification<Student> spec = new Specification<Student>() {
			//1. 构造查询条件对象
			List<Predicate> predicates = new ArrayList<>();

			@Override
			public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				if(StrUtil.isNotBlank(vo.getSname())){
					predicates.add(cb.like(root.get("sname").as(String.class),"%" + vo.getSname() + "%"));
				}
				if(StrUtil.isNotBlank(vo.getAddr())){
					predicates.add(cb.like(root.get("addr").as(String.class),"%" + vo.getAddr() + "%"));
				}
				if(vo.getCid() != null && vo.getCid() != 0){
					predicates.add(cb.equal(root.get("cid").as(Integer.class),vo.getCid()));
				}
				// 将集合转换为一个数组
				return cb.and(predicates.toArray(new Predicate[predicates.size()]));
			}
		};
		Page<Student> studentPage = dao.findAll(spec, PageRequest.of(page - 1, pageSize));

		return  new PageResult<>(studentPage.getContent(),new Long(studentPage.getTotalPages()+""));
	}

	//4.  添加学生
	@Override
	public void insert(Student student) {
		dao.save(student);
	}

	// 版本一：使用RedisTemplate
	@Override
	public List<Student> list() {
		//1. 从redis中取得学生列表
		ValueOperations operations = redisTemplate.opsForValue();
		List<Student> studentList = (List<Student>) operations.get("studentList");
		//2. 如果redis中没有数据，就从数据库中查询
		if(studentList == null || studentList.size() == 0){
			log.info("正在从数据库中查询学生列表");
			studentList = dao.findAll();
			//2.1 将查询出的数据放到redis中
			//参数1：代表redis的key
			//参数2：代表存放的值
			//参数3：存放时间（过期时间）
			//参数4：时间单位
			// redisTemplate.opsForValue().set("studentList",studentList,10, TimeUnit.HOURS);
		}
		return studentList;
	}

	// 版本二：使用StringRedisTemplate （不需要进行序列化）
	@Override
	public List<Student> list2() {
		List<Student> studentList = null;
		//1. 从redis中取得学生列表
		ValueOperations<String,String> operations = redisTemplate.opsForValue();
		String str = operations.get("studentList2");
		//2. 如果redis中没有数据，就从数据库中查询
		if(StrUtil.isBlank(str)){
			log.info("正在从数据库中查询学生列表");
			studentList = dao.findAll();
			//2.1 将查询出的数据放到redis中
			//参数1：代表redis的key
			//参数2：代表存放的值
			//参数3：存放时间（过期时间）
			//参数4：时间单位
			redisTemplate.opsForValue().set("studentList2", JSON.toJSONString(studentList),10, TimeUnit.HOURS);
		}else{
			System.out.println("redis命中...");
			studentList = JSON.parseArray(str,Student.class);
		}
		return studentList;
	}

	//3. 在添加时删除redis中的数据
	@Override
	public void add(Student student) {
		redisTemplate.delete("studentList2");
		dao.save(student);
	}

	//4.  根据id查询学生
	@Override
	public Student findById(int sid) {
		return dao.findById(Long.parseLong(sid + "")).get();
	}

	//5. 修改学生
	@Override
	public void update(Student student) {
		//从reds中删除此学生列表
		redisTemplate.delete("studentList2");
		dao.save(student);
	}

	//6. 根据主键删除学生
	@Override
	public void delete(int sid) {
		//从reds中删除此学生列表
		redisTemplate.delete("studentList2");
		//从数据库根据sid删除学生
		dao.deleteById(new Long(sid + ""));
	}
}

